package com.hjj.springboot.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hjj.springboot.entity.Comment;
import com.hjj.springboot.entity.OrderDetail;
import com.hjj.springboot.mapper.CommentMapper;
import com.hjj.springboot.mapper.OrderDetailMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户购物行为计算器
 */
@Component
@Slf4j
public class UserBehaviorCalculator {

    private static final double PURCHASE_WEIGHT = 0.6; // 购买权重
    private static final double RATING_WEIGHT = 0.4; // 评分权重
    private static final double DEFAULT_NORMALIZED_SCORE = 0.5; // 默认归一化分数

    private final OrderDetailMapper orderDetailMapper;
    private final CommentMapper commentMapper;

    public UserBehaviorCalculator(OrderDetailMapper orderDetailMapper, CommentMapper commentMapper) {
        this.orderDetailMapper = orderDetailMapper;
        this.commentMapper = commentMapper;
    }

    public Map<Integer, Double> calculateUserPreferences(String userId) {
        try {
            // 查询用户购买数据
            Map<Integer, Integer> purchaseData = getPurchaseData(userId);
            // 查询用户评分数据
            Map<Integer, Double> ratingData = getRatingData(userId);
            // 计算用户购物行为分数
            Map<Integer, Double> productScores = mergeAndCalculateScores(purchaseData, ratingData);
            return normalizeScores(productScores);
        } catch (Exception e) {
            log.error("计算用户购物爱好行为失败, userId: {}", userId, e);
            return Collections.emptyMap();
        }
    }

    private Map<Integer, Integer> getPurchaseData(String userId) {
        // 先查询用户数据
        List<OrderDetail> details = orderDetailMapper.selectUserPurchaseDetails(userId);

        // 用户无数据时查询全局数据
        if (details.isEmpty()) {
            details = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().select("goodsId", "goodsNumber"));
        }
        return details.stream()
                .collect(Collectors.groupingBy(
                        OrderDetail::getGoodsId,
                        Collectors.summingInt(OrderDetail::getGoodsNumber)
                ));
    }

    private Map<Integer, Double> getRatingData(String userId) {
        // 先查询用户数据
        List<Comment> comments = commentMapper.selectList(new QueryWrapper<Comment>().eq("uId", userId));

        // 用户无数据时查询全局数据
        if (comments.isEmpty()) {
            comments = commentMapper.selectList(new QueryWrapper<Comment>().select("gId", "scores"));
        }
        return comments.stream()
                .collect(Collectors.groupingBy(
                        Comment::getGId,
                        Collectors.averagingInt(Comment::getScores)
                ));
    }

    private Map<Integer, Double> mergeAndCalculateScores(
            Map<Integer, Integer> purchaseData,
            Map<Integer, Double> ratingData
    ) {
        // 分别归一化购买次数和评分
        Map<Integer, Double> normalizedPurchase = normalizePurchaseData(purchaseData);
        Map<Integer, Double> normalizedRating = normalizeRatingData(ratingData);

        Set<Integer> allProductIds = new HashSet<>();
        allProductIds.addAll(purchaseData.keySet());
        allProductIds.addAll(ratingData.keySet());

        return allProductIds.stream()
                .collect(Collectors.toMap(
                        productId -> productId,
                        productId ->
                                normalizedPurchase.getOrDefault(productId, 0.0) * PURCHASE_WEIGHT +
                                        normalizedRating.getOrDefault(productId, 0.0) * RATING_WEIGHT
                ));
    }

    private Map<Integer, Double> normalizePurchaseData(Map<Integer, Integer> purchaseData) {
        if (purchaseData.isEmpty()) {
            return Collections.emptyMap();
        }

        DoubleSummaryStatistics stats = purchaseData.values().stream()
                .mapToDouble(Integer::doubleValue)
                .summaryStatistics();

        return purchaseData.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> calculateNormalizedValue(entry.getValue(), stats.getMin(), stats.getMax())
                ));
    }

    private Map<Integer, Double> normalizeRatingData(Map<Integer, Double> ratingData) {
        if (ratingData.isEmpty()) {
            return Collections.emptyMap();
        }

        DoubleSummaryStatistics stats = ratingData.values().stream()
                .mapToDouble(Double::doubleValue)
                .summaryStatistics();

        return ratingData.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> calculateNormalizedValue(entry.getValue(), stats.getMin(), stats.getMax())
                ));
    }

    private Map<Integer, Double> normalizeScores(Map<Integer, Double> scores) {
        if (scores.isEmpty()) {
            return scores;
        }

        DoubleSummaryStatistics stats = scores.values()
                .stream()
                .mapToDouble(Double::doubleValue)
                .summaryStatistics();

        return scores.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> calculateNormalizedValue(entry.getValue(), stats.getMin(), stats.getMax())
                ));
    }

    private double calculateNormalizedValue(double value, double min, double max) {
        return (Math.abs(max - min) < 1e-10) ?
                DEFAULT_NORMALIZED_SCORE :
                (value - min) / (max - min);
    }
}

